{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 第 4 章：神经网络基础"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "plt.rcParams['font.sans-serif']=['SimHei']\n",
    "plt.rcParams['axes.unicode_minus']=False"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 逻辑回归"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 数据集"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "从 `sklearn` 库中导入 `make_moon` 数据集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sklearn.datasets\n",
    "\n",
    "np.random.seed(1)    # 设置随机种子\n",
    "X, Y = sklearn.datasets.make_moons(n_samples=200, noise=.2)    # 导入 make_moon 数据集，样本个数 m=200，噪声标准差为 0.2\n",
    "X, Y = X.T, Y.reshape(1, Y.shape[0])    # X shape: [2,200]，Y shape: [1,200]\n",
    "m = X.shape[1]    # 样本个数\n",
    "dim = X.shape[0]    # 特征维度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "X shape:  (2, 200)\n",
      "Y shape:  (1, 200)\n"
     ]
    }
   ],
   "source": [
    "print('X shape: ', X.shape)\n",
    "print('Y shape: ', Y.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "绘制数据分布散点图"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.scatter(X[0, Y[0,:]==0], X[1, Y[0,:]==0], c='r', marker='s')    # 负类\n",
    "plt.scatter(X[0, Y[0,:]==1], X[1, Y[0,:]==1], c='b', marker='o')    # 正类\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 梯度下降优化算法"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "代价函数（Cost Fucntion）："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$J=-\\frac{1}{m}\\sum_{i=1}^{m}y^{(i)}log\\hat y^{(i)}+(1-y^{(i)})log(1-\\hat y^{(i)})$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "梯度下降（Gradient Descent）："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\\frac{\\partial J}{\\partial W} = \\frac{1}{m}X(\\hat Y-Y)^T$$\n",
    "$$\\frac{\\partial J}{\\partial b} = \\frac{1}{m} \\sum_{i=1}^m (\\hat y^{(i)}-y^{(i)})$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "定义 Sigmoid 函数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def sigmoid(x):\n",
    "    \"\"\"\n",
    "    函数输入：\n",
    "        - x：sigmoid 函数输入\n",
    "\n",
    "    函数输出：\n",
    "        - y：sigmoid 输出\n",
    "    \"\"\"\n",
    "    y = 1 / (1 + np.exp(-x))\n",
    "    \n",
    "    return y"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "定义逻辑回归优化算法："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def optimizer(X, Y, num_iterations=200, learning_rate=0.01):\n",
    "    \"\"\"\n",
    "    函数输入：\n",
    "        - X：输入数据特征，维度 = (dim, m)\n",
    "        - Y：输入数据标签，维度 = (1, m)\n",
    "        - num_iteration：训练次数\n",
    "        - learning_rate：学习速率\n",
    "    函数输出：\n",
    "        - W：训练后的权重参数\n",
    "        - b：训练后的偏置参数\n",
    "        - cost：每次训练计算的损失存放在 cost 列表中\n",
    "    \"\"\"\n",
    "    cost = []         # 列表，存放每次训练的损失\n",
    "    m = X.shape[1]    # 样本个数\n",
    "    dim = X.shape[0]  # 特征维度\n",
    "    \n",
    "    # 参数初始化\n",
    "    W = np.zeros((dim, 1))\n",
    "    b = 0\n",
    "    \n",
    "    # 迭代训练\n",
    "    for i in range(num_iterations):\n",
    "        Z = np.dot(W.T, X) + b    # 线性部分\n",
    "        Y_hat = sigmoid(Z)    # 非线性部分\n",
    "        J = -1.0 / m * np.sum(Y * np.log(Y_hat) + (1 - Y) * np.log(1 - Y_hat))    # 代价函数\n",
    "        cost.append(J)\n",
    "        \n",
    "        # 梯度下降\n",
    "        dW = 1.0 / m * np.dot(X, (Y_hat - Y).T)\n",
    "        db = 1.0 / m * np.sum(Y_hat - Y)\n",
    "        W = W - learning_rate * dW    # W 更新公式\n",
    "        b = b - learning_rate * db    # b 更新公式\n",
    "    \n",
    "        if (i+1) % 20 == 0:\n",
    "            print('Iteration: %d, J = %f' % (i+1, J))\n",
    "        \n",
    "    return W, b, cost"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Iteration: 20, J = 0.566442\n",
      "Iteration: 40, J = 0.496925\n",
      "Iteration: 60, J = 0.455583\n",
      "Iteration: 80, J = 0.428317\n",
      "Iteration: 100, J = 0.408968\n",
      "Iteration: 120, J = 0.394467\n",
      "Iteration: 140, J = 0.383137\n",
      "Iteration: 160, J = 0.373990\n",
      "Iteration: 180, J = 0.366413\n",
      "Iteration: 200, J = 0.360008\n",
      "Iteration: 220, J = 0.354504\n",
      "Iteration: 240, J = 0.349710\n",
      "Iteration: 260, J = 0.345489\n",
      "Iteration: 280, J = 0.341740\n",
      "Iteration: 300, J = 0.338385\n",
      "Iteration: 320, J = 0.335364\n",
      "Iteration: 340, J = 0.332631\n",
      "Iteration: 360, J = 0.330146\n",
      "Iteration: 380, J = 0.327878\n",
      "Iteration: 400, J = 0.325803\n",
      "Iteration: 420, J = 0.323897\n",
      "Iteration: 440, J = 0.322143\n",
      "Iteration: 460, J = 0.320525\n",
      "Iteration: 480, J = 0.319029\n",
      "Iteration: 500, J = 0.317644\n",
      "Iteration: 520, J = 0.316360\n",
      "Iteration: 540, J = 0.315166\n",
      "Iteration: 560, J = 0.314056\n",
      "Iteration: 580, J = 0.313022\n",
      "Iteration: 600, J = 0.312057\n",
      "Iteration: 620, J = 0.311156\n",
      "Iteration: 640, J = 0.310314\n",
      "Iteration: 660, J = 0.309526\n",
      "Iteration: 680, J = 0.308788\n",
      "Iteration: 700, J = 0.308096\n",
      "Iteration: 720, J = 0.307447\n",
      "Iteration: 740, J = 0.306837\n",
      "Iteration: 760, J = 0.306264\n",
      "Iteration: 780, J = 0.305725\n",
      "Iteration: 800, J = 0.305218\n",
      "Iteration: 820, J = 0.304740\n",
      "Iteration: 840, J = 0.304289\n",
      "Iteration: 860, J = 0.303864\n",
      "Iteration: 880, J = 0.303463\n",
      "Iteration: 900, J = 0.303084\n",
      "Iteration: 920, J = 0.302725\n",
      "Iteration: 940, J = 0.302387\n",
      "Iteration: 960, J = 0.302066\n",
      "Iteration: 980, J = 0.301763\n",
      "Iteration: 1000, J = 0.301476\n"
     ]
    }
   ],
   "source": [
    "W, b, cost = optimizer(X, Y, num_iterations=1000, learning_rate=0.1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "训练后的参数 $W$ 和 $b$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "W =  [[ 1.14042339]\n",
      " [-3.83196763]]\n",
      "b =  0.3501017350326183\n"
     ]
    }
   ],
   "source": [
    "print('W = ', W)\n",
    "print('b = ', b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "显示训练过程中的损失 cost"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(cost)\n",
    "plt.xlabel('迭代次数')\n",
    "plt.ylabel('损失函数')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 预测"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "定义预测函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def predict(X, W, b):\n",
    "    \"\"\"\n",
    "    函数输入：\n",
    "        - X：输入数据特征，维度 = (dim, m)\n",
    "        - W：训练后的权重参数\n",
    "        - b：训练后的偏置参数\n",
    "    函数输出：\n",
    "        - Y_pred：预测输出标签，维度 = (1, m)\n",
    "    \"\"\"\n",
    "    \n",
    "    Y_pred = np.zeros((1, X.shape[1]))    # 初始化 Y_pred\n",
    "    \n",
    "    Z = np.dot(W.T, X) + b    # 线性部分\n",
    "    Y_hat = sigmoid(Z)    # 非线性部分\n",
    "    Y_pred[Y_hat > 0.5] = 1    # Y_hat 大于 0.5 的预测为正类\n",
    "\n",
    "    return Y_pred"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对输入数据 X 进行预测"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0. 0. 0. 0. 1. 1. 0. 1. 0. 1. 1. 0. 1. 0. 0. 1. 1. 0. 1. 0. 0. 0. 0. 0.\n",
      "  0. 1. 0. 0. 1. 0. 0. 1. 1. 1. 1. 1. 1. 0. 0. 1. 1. 0. 1. 0. 0. 0. 0. 0.\n",
      "  1. 1. 1. 1. 1. 0. 0. 1. 1. 0. 1. 1. 0. 0. 0. 0. 0. 1. 1. 0. 0. 0. 0. 0.\n",
      "  1. 1. 1. 1. 0. 0. 0. 1. 1. 0. 0. 1. 1. 0. 0. 1. 1. 0. 0. 0. 1. 1. 1. 0.\n",
      "  1. 1. 1. 1. 0. 0. 0. 1. 1. 0. 0. 1. 1. 0. 1. 1. 0. 0. 0. 1. 0. 1. 0. 0.\n",
      "  0. 0. 1. 1. 1. 0. 1. 1. 1. 1. 0. 0. 1. 0. 1. 0. 1. 1. 1. 0. 1. 1. 1. 1.\n",
      "  0. 1. 0. 1. 1. 0. 0. 0. 0. 0. 0. 1. 1. 0. 1. 1. 1. 0. 1. 1. 1. 1. 0. 1.\n",
      "  1. 0. 0. 0. 0. 1. 1. 1. 0. 0. 0. 0. 1. 1. 1. 1. 1. 0. 0. 1. 0. 1. 0. 1.\n",
      "  1. 1. 0. 1. 1. 0. 1. 0.]]\n"
     ]
    }
   ],
   "source": [
    "Y_pred = predict(X, W, b)\n",
    "print(Y_pred)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "计算预测准确率"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.86\n"
     ]
    }
   ],
   "source": [
    "accuracy = np.mean(Y_pred == Y)\n",
    "print(accuracy)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "绘制分类直线，可视化分类效果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from matplotlib.colors import ListedColormap\n",
    "    \n",
    "x_min, x_max = X[0, :].min() - 0.5, X[0, :].max() + 0.5\n",
    "y_min, y_max = X[1, :].min() - 0.5, X[1, :].max() + 0.5\n",
    "step = 0.001\n",
    "xx, yy = np.meshgrid(np.arange(x_min, x_max, step), np.arange(y_min, y_max, step))\n",
    "Z = predict(np.c_[xx.ravel(), yy.ravel()].T, W, b)\n",
    "Z = Z.reshape(xx.shape)\n",
    "plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral)    # 绘制边界\n",
    "plt.scatter(X[0, Y[0,:]==0], X[1, Y[0,:]==0], c='g', marker='s', label='负类')    # 负类\n",
    "plt.scatter(X[0, Y[0,:]==1], X[1, Y[0,:]==1], c='y', marker='o', label='正类')    # 正类\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
